package com.gking.resourcePool.interceptor;


import com.gking.resourcePool.common.BaseContext;
import com.gking.resourcePool.utils.GetAuthInfoUtil;
import com.gking.resourcePool.entity.LogsRecord;
import com.gking.resourcePool.service.LogsRecord.LogsRecordService;
import com.gking.resourcePool.utils.commoUtil.CustomEncryptorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 日志拦截器
 */
@Slf4j
public class LoggingInterceptor implements HandlerInterceptor {

    private final LogsRecordService logsRecordService;
    private static final String REQUEST_START_TIME_ATTRIBUTE = "REQUEST_START_TIME";


    public LoggingInterceptor(LogsRecordService logsRecordService) {
        this.logsRecordService = logsRecordService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) {
        log.info("系统日志开始记录。。。");
        // 在请求开始时记录当前时间, 存储纳秒级别的开始时间戳
        request.setAttribute(REQUEST_START_TIME_ATTRIBUTE, System.nanoTime());
        return true; // 继续处理请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) {
        String token = request.getHeader("Authorization");
        String requestURI = request.getRequestURI();
        // 获取到的请求param参数
        String parameter = getRequestParameter(request);
        // 获取到的请求body参数
        String bodyParam;
        if (check(requestURI)) bodyParam = "文件资源";
        else bodyParam = getRequestBody(request);
        Integer statusCode = response.getStatus();
        String consumeTime = null;
        String remoteAddr = GetAuthInfoUtil.getClientIp(request);
        String equipmentInfo = request.getHeader("User-Agent");

        Long startTime = (Long) request.getAttribute(REQUEST_START_TIME_ATTRIBUTE);
        if (startTime != null) {
            long durationMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
            consumeTime = durationMillis + "ms";
        }

        // 在请求完成后执行,可以记录耗时等信息
        LogsRecord logsRecord = new LogsRecord();

        if (token != null) {
            String userId = GetAuthInfoUtil.getUserId(token);
            logsRecord.setAccessUserId(userId);
        }

        if (parameter == null) logsRecord.setAccessPath(requestURI);
        else logsRecord.setAccessPath(requestURI + "?" + parameter);

        logsRecord.setRequestBody(CustomEncryptorUtil.encryption(bodyParam));
        logsRecord.setAccessStatus(statusCode + "");
        logsRecord.setResponseMessage(BaseContext.getResponseMessage());
        logsRecord.setResponseStatus(BaseContext.getResponseCode());
        logsRecord.setConsumeTime(consumeTime);
        logsRecord.setCreateTime(LocalDateTime.now());
        logsRecord.setIpAddress(remoteAddr);
        logsRecord.setEquipmentInfo(equipmentInfo);

        logsRecordService.addLogsRecord(logsRecord);

        //销毁保存的数据
        BaseContext.destroy();
    }

    /**
     * 路径匹配，检查本次不需要处理的请求路径
     *
     * @param requestURI 前端发起的请求
     * @return s
     */
    private boolean check(String requestURI) {
        //定义不需要处理的请求路径
        String[] urls = new String[]{
                "/resource/upload",
                "/resource/upload/**",
        };
        //路径匹配器，支持通配符
        AntPathMatcher PATH_MATCHER = new AntPathMatcher();

        for (String url : urls) {
            boolean match = PATH_MATCHER.match(url, requestURI);
            if (match) return true;
        }
        return false;
    }


    /**
     * 获取请求的 param 参数
     *
     * @param request 请求
     * @return param参数字符串
     */
    private String getRequestParameter(HttpServletRequest request) {
        StringBuilder parameterStr = new StringBuilder();

        // 获取请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String paramName = entry.getKey();
            String[] paramValues = entry.getValue();
            StringBuilder paramValueBuilder = new StringBuilder();
            for (String value : paramValues) paramValueBuilder.append(value);
            parameterStr.append(paramName).append("=").append(paramValueBuilder).append("&");
        }

        if (parameterStr.length() == 0) return null;
        return parameterStr.substring(0, parameterStr.length() - 1);
    }


    /**
     * 获取请求的 body 参数
     *
     * @param request 请求
     * @return body参数字符串
     */
    private String getRequestBody(HttpServletRequest request) {
        StringBuilder data = new StringBuilder();
        String line;
        BufferedReader reader;
        try {
            reader = request.getReader();
            while (null != (line = reader.readLine())) data.append(line);
        } catch (IOException e) {
            return null;
        }
        return data.toString();
    }


}
